package kin.dao.system;

import java.io.Serializable;


import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.ArrayList;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


import javax.inject.Inject;



import kin.bean.system.Form;
import kin.bean.system.M2M;
import kin.bean.system.M2O;
import kin.bean.system.MyEnumType;
import kin.bean.system.O2M;
import kin.bean.system.O2O;
import kin.bean.system.Result;

import kin.manager.system.BaseManager;



import kin.system.util.DeepQuery;
import kin.system.util.StringUtil;
import kin.system.util.ValueOfType;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;


import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.transform.Transformers;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.stereotype.Component;



public abstract class BaseManagerIMP<T> implements BaseManager<T> {
	protected Class<T> entityClass;
	/*@Inject
private LocalSessionFactoryBean localSessionFactoryBean;*/
	@Inject
  private SessionFactory sessionFactory;
	
	public List exportExcel(String query){
		return null;
		
	}
 
	public BaseManagerIMP() {
		
		entityClass = getSuperClassGenricType(this.getClass());
		//Iterator<PersistentClass> it=this.getLocalSessionFactoryBean().getConfiguration().getClassMappings();
		System.out.println(" BaseManagerIMP()======" + entityClass.getName());
	}

	public Class getSuperClassGenricType(Class clazz) {
		Type genType = clazz.getGenericSuperclass();

		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}

		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

		if (!(params[0] instanceof Class)) {
			return Object.class;
		}
		return (Class) params[0];
	}

	  public List<T> findList(LinkedHashMap<String, Object> where,LinkedHashMap<String, Collection> in,LinkedHashMap<String, Boolean> orderby,LinkedHashMap<String, Collection> like)throws Exception{
		  List l = null;
		  Criteria cra=this.getSessionFactory().getCurrentSession().createCriteria(entityClass);
		  
		 
		 
		 
		  if(like!=null){
			  for (Map.Entry<String, Collection> entry : like.entrySet()) {
					 String key = entry.getKey();
					 Collection value = entry.getValue();
					 Iterator lp=value.iterator();
					 System.out.println("pl---value:"+value);
					 while(lp.hasNext()){
						 System.out.println("pl:"+lp.next());
					 }
					 cra.add(Restrictions.like(key, value));
					 }	
		  }
		  
			if(where!=null){
				for (Map.Entry<String,Object> entry : where.entrySet()) {
					 String key = entry.getKey();
					 Object value = entry.getValue();
					 if("Null".equals(value)){
						 cra.add(Property.forName(key).isNull()); 
					 }else{
					 cra.add(Property.forName(key).eq(value));
					 }
					 }	
			}
			
			  if(in!=null){
	            	for (Map.Entry<String, Collection> entry : in.entrySet()) {
						 String key = entry.getKey();
						 Collection value = entry.getValue();
						 Iterator lp=value.iterator();
						 System.out.println("pl---value:"+value);
						 while(lp.hasNext()){
							 System.out.println("pl:"+lp.next());
						 }
						 cra.add(Restrictions.in(key, value));
						 }	
				}
	            if(orderby!=null){
					for (Map.Entry<String,Boolean> entry : orderby.entrySet()) {
						 String key = entry.getKey();
						 Boolean value = entry.getValue();
						 if(value){
						 cra.addOrder(Order.asc(key));
						 } else{
						 cra.addOrder(Order.desc(key)); 
						 }
						 }
					
				}
			l=cra.list();
		return l;
		  
	  }
	  
	  public void deleteAll(){
	List<T> ls= this.findAll();
	for(T t:ls){
		this.getSessionFactory().getCurrentSession().delete(t);
	}
		  //this.getSessionFactory().getCurrentSession().createQuery("delete "+entityClass.getSimpleName()).executeUpdate();
		  
	  }

      public Result findPaging(LinkedHashMap<String, Object> where,LinkedHashMap<String, String[]> in,LinkedHashMap<String, Boolean> orderby,int page,int start,int pageSize)throws Exception{
    	  Result result=new Result();
    	  Criteria cra=this.getSessionFactory().getCurrentSession().createCriteria(entityClass);
    	
    	/*  Criteria craform=this.getSessionFactory().getCurrentSession().createCriteria(Class.forName("kin.system.bean.Form"));
  		    List<String> list=new ArrayList<String>();
  		  
			
  			LinkedHashMap<String, Object> ll=new LinkedHashMap<String, Object>();
        	ll.put("form_name", entityClass.getSimpleName());
        	Form f = (Form)craform.add(Property.forName("form_name").eq(entityClass.getSimpleName())).uniqueResult();
			Set<O2M> o2ms=f.getO2ms();
			Iterator o2mi=o2ms.iterator();
			while(o2mi.hasNext()){
				O2M o2m=(O2M) o2mi.next();
				list.add(StringUtil.fristLetterLowerCase(o2m.getName()));
			}
			Set<O2O> o2os=f.getO2os();
			Iterator o2oi=o2os.iterator();
			while(o2oi.hasNext()){
				O2O o2o=(O2O) o2oi.next();
				list.add(StringUtil.fristLetterLowerCase(o2o.getName()));
			}
			
			Set<M2O> m2os=f.getM2os();
			Iterator m2oi=m2os.iterator();
			while(m2oi.hasNext()){
				M2O m2o=(M2O) m2oi.next();
				list.add(StringUtil.fristLetterLowerCase(m2o.getName()));
			}
			Set<M2M> m2ms=f.getM2ms();
			Iterator m2mi=m2ms.iterator();
			while(m2mi.hasNext()){
				M2M m2m=(M2M) m2mi.next();
				list.add(StringUtil.fristLetterLowerCase(m2m.getName()));
			}
    	
		
			for(String s:list){
				 System.out.println("-----------list:"+s);
				 }
    	  

			if(where!=null){
				for (Map.Entry<String,Object> entry : where.entrySet()) {
					 String key = entry.getKey();
					 System.out.println("-----------inside:"+key);
					 
					 Object value = entry.getValue();
					 if(list.contains(key)){
						 System.out.println("-----------inside");
						 
						 //cra.setFetchMode(key, FetchMode.JOIN);
						 Criteria sub=cra.createCriteria(key);
						sub.add(Property.forName(key+"_id").eq(Integer.parseInt((String)value)));
						// sub.add( Restrictions.idEq(Integer.parseInt((String)value)));
						 //Expression.eq( key+"."+key+"_id" ,  childName);
					 }else{
					 if(this.entityClass.getDeclaredField(key).getType().isEnum()){
						 MyEnumType v=	 MyEnumType.valueOf(MyEnumType.format(Integer.parseInt((String) value) ));
						 cra.add(Property.forName(key).eq(v)); 
					 }else{
						 System.out.println("-------ooooooooo");
						 cra.add(Property.forName(key).eq(ValueOfType.covertor(entityClass, key, (String)value))); 
					 }
					 } 
					 }
				
			}
			if(in!=null){
				for (Map.Entry<String,String[]> entry : in.entrySet()) {
					
					 String key = entry.getKey();
					 String[] value = entry.getValue();
					 
					 if(list.contains(key)){
						 System.out.println("value:"+value);
						 List<Integer> l=new ArrayList<Integer>();
						 for(String s:value){
							 if("".equals(s)){
								 l.add(0);
								System.out.println("value is empty");
							 }else{
							 l.add(Integer.parseInt(s));
							 }	 }
						 
							cra.createCriteria(key).add(Restrictions.in(key+"_id", l));
							 
							 
						 }else{
					 if(this.entityClass.getDeclaredField(key).getType().isEnum()){
						 List<MyEnumType> li = new ArrayList<MyEnumType>();	 
						 for(String s:value){
							 MyEnumType v=	 MyEnumType.valueOf(MyEnumType.format(Integer.parseInt((String) s) ));
							 li.add(v);
						 }
						 cra.add(Property.forName(key).in(li)); 
					 }else{
						 List li = new ArrayList();	
						 for(String s:value){
							 li.add(ValueOfType.covertor(entityClass, key, s));
						 }
						 cra.add(Property.forName(key).in(li));
					 }
					 System.out.println("value:"+value);
						 }
					 }
			}
			if(orderby!=null){
				for (Map.Entry<String,Boolean> entry : orderby.entrySet()) {
					 String key = entry.getKey();
					 Boolean value = entry.getValue();
					 if(value){
					 cra.addOrder(Order.asc(key));
					 } else{
					 cra.addOrder(Order.desc(key)); 
					 }
					 }
			}
			
			Criteria criteria = cra.setResultTransformer(Criteria.ROOT_ENTITY);
			List re = criteria.list();
            if (!re.isEmpty()) {
                Integer rowCount = (Integer) re.get(0);
                result.setTotal(rowCount);
            }
			
			if(page>0){
				
				
				
                 cra.setFirstResult(start).setMaxResults(pageSize);
                
                 
        
			}*/
			List lt=cra.list();
			for(int a=0;a<lt.size();a++){
				System.out.println("rrr:"+lt.get(a));
			}
			
			//result.setList(list);
			//result.setList(cra.list());
			return   result;
    	  
      }
		
		public void delete(Serializable id) {
			
				this.getSessionFactory().getCurrentSession().delete(load(id));
			
		}
		
		public T find(LinkedHashMap<String, Object> where,LinkedHashMap<String, Boolean> orderby,String className){
			T t=null;
			Criteria cra = null;
			if(null==className){
			cra=this.getSessionFactory().getCurrentSession().createCriteria(this.entityClass);
			}else{
				cra=this.getSessionFactory().getCurrentSession().createCriteria(className);
			}
			if(where!=null){
				for (Map.Entry<String,Object> entry : where.entrySet()) {
					 String key = entry.getKey();
					 Object value = entry.getValue();
					 cra.add(Restrictions.eq(key, value));
					 }
				
			}
			if(orderby!=null){
				for (Map.Entry<String,Boolean> entry : orderby.entrySet()) {
					 String key = entry.getKey();
					 Boolean value = entry.getValue();
					 if(value){
					 cra.addOrder(Order.asc(key));
					 } else{
					 cra.addOrder(Order.desc(key)); 
					 }
					 }
				
			}
			/*List l=cra.uniqueResult();
           if(l.size()>0){
        	   t=(T) l.get(0);
           }*/
			return (T) cra.uniqueResult();
			
		}
		
	

	public List<T> findAll() {
		//this.getSessionFactory().getCurrentSession().createCriteria(this.entityClass);
		//hibernateTemplate.findByCriteria(DetachedCriteria.forClass(entityClass));
		return this.getSessionFactory().getCurrentSession().createCriteria(this.entityClass).list();
	}

	public T load(Serializable id) {

		return (T) this.getSessionFactory().getCurrentSession().load(entityClass, id);
	}

	public T get(Serializable id) {

		return (T) this.getSessionFactory().getCurrentSession().get(entityClass, id);
	}

	public void add(T entity) {
		this.getSessionFactory().getCurrentSession().save(entity);
	}

	
	
	

	private static <P> String getRealName(Class<P> entityClass2) {
		String RealName = entityClass2.getSimpleName();
		return RealName;
	}
	
	

	public void update(Object entity) {
		
		this.getSessionFactory().getCurrentSession().saveOrUpdate(entity);
	}
    
    
	
	
	
	
	
	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}


	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/*public LocalSessionFactoryBean getLocalSessionFactoryBean() {
		return localSessionFactoryBean;
	}*/

/*	public void setLocalSessionFactoryBean(
			LocalSessionFactoryBean localSessionFactoryBean) {
		this.localSessionFactoryBean = localSessionFactoryBean;
	}*/


  






/*public SessionFactory getCustomerSessionFactory() {
	return customerSessionFactory;
}

public void setCustomerSessionFactory(SessionFactory customerSessionFactory) {
	this.customerSessionFactory = customerSessionFactory;
}*/

	

	
	
	
}
